package com.runa.monitor.platinterface.netservice.client;

import com.runa.monitor.comm.entity.CommNetService;
import com.runa.monitor.platinterface.netservice.connect.Session;
import com.runa.monitor.platinterface.netservice.equipment.NetEqu;
import com.runa.monitor.platinterface.netservice.equipment.furuisi.FuRuiSiClientDriver;
import com.runa.monitor.platinterface.netservice.handler.ConcenChannelInitializer;
import com.runa.monitor.platinterface.netservice.server.Server;
import com.runa.persistence.util.LogUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 2024/12/4 14:40
 * zhangYB
 */
@Slf4j
public class ConcentratorClient extends Server {

    private Bootstrap bootstrap;
    protected ChannelFuture future;
    private Channel channel;
    private CommNetService service;
    protected static final Map<String, ConcentratorClient> SERVERS = new ConcurrentHashMap<>();
    private static final Map<String, ConcentratorClient> CHANNEL_SERVERS = new HashMap<>();

    private NetEqu netEqu;

    public ConcentratorClient(CommNetService service) {
        this.service = service;
        bootstrap = new Bootstrap()
                .group(new NioEventLoopGroup(1))
                .channel(NioSocketChannel.class)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
                .handler(new ConcenChannelInitializer(service.getProtocol(), true));
        start();
    }

    public CommNetService getService() {
        return service;
    }

    public void setNetEqu(NetEqu netEqu) {
        this.netEqu = netEqu;
    }

    public NetEqu getNetEqu() {
        return netEqu;
    }

    public static ConcentratorClient getInstance(CommNetService service) {
        String key = service.getIp() + ":" + service.getPort();
        ConcentratorClient concentratorClient = SERVERS.get(key);
        if (null == concentratorClient) {
            synchronized (SERVERS) {
                concentratorClient = new ConcentratorClient(service);
                SERVERS.put(key, concentratorClient);
            }
        }
        return concentratorClient;
    }

    public void start() {
        Timer timer = new Timer(service.getName());
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (!isConnected()) {
                    connect();
                }
            }
        }, 1000, 60 * 1000);
    }

    public boolean connect() {
        try {
            if (null == service) {
                return false;
            }
            if (null == service.getIp() || null == service.getPort()) {
                return false;
            }
            future = bootstrap.connect(service.getIp(), service.getPort()).sync();
            if (future.isSuccess()) {
                channel = future.channel();
                connectSuccess();
                return true;
            }
        } catch (Exception e) {
            log.error("connect: {}", e);
        }
        return false;
    }


    public static ConcentratorClient getInstanceByChannelId(String channelId) {
        return CHANNEL_SERVERS.get(channelId);
    }

    public void connectSuccess() {
        CHANNEL_SERVERS.put(getChannel().id().asLongText(), this);
        LogUtil.getLogAndInfo(service.getName(), "客户端", getChannel().id().asLongText());
    }

    @Override
    public void reConnect(Session session) {

    }

    public Channel getChannel() {
        return channel;
    }

    @Override
    public boolean shutdown() {
        try {
            channel.close();
            SERVERS.remove(service.getIp() + ":" + service.getPort());
            channel = null;
            future = null;
        } catch (Exception e) {
            log.error("ConcentratorClient.shutdown: ", e);
            return false;
        }
        return true;
    }

    public boolean isConnected() {
        return null != channel && channel.isActive();
    }
}
